import { Injector, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppRoutingModule } from './app-routing.module';
import { SharedModule } from './shared/shared.module';
// import { FilterTextComponent } from './shared/filter-text/filter-text.component';

// Do gather application-wide, single use components in the CoreModule. Import it once (in the AppModule) when 
// the app starts and never import it anywhere else. (e.g. NavComponent and SpinnerComponent).

// Why? Real world apps can have several single-use components (e.g., spinners, message toasts, and modal dialogs) 
// that appear only in the AppComponent template. They are not imported elsewhere so they're not shared in that sense. 
// Yet they're too big and messy to leave loose in the root folder.
import { CoreModule } from './core/core.module';
import { MaterialModule } from './core/modules/material.module';
import { ServiceLocator } from './core/shared/service.locator';
import { AuthenticationModule } from './authentication/authentication.module';
// import { UserService } from './users/shared/user.service';

import { AppComponent } from './app.component';
import { LockScreenComponent } from './authentication/lock-screen/lock-screen.component';
import { UsersModule } from './users/users.module';

// Modules don't inherit access to the components, directives, or pipes that are declared in other modules. 
// What AppModule imports is irrelevant to other modules and vice versa. 

@NgModule({
    // Other modules whose exported classes are needed by component templates declared in THIS module.
    // Module import order matters.
    imports: [
        // Importing BrowserModule made all of its public components, directives, and pipes visible to the component templates in AppModule.
        // BrowserModule registers critical application service providers. It also includes common directives like 
        // NgIf and NgFor, which become immediately visible and usable in any of THIS module's component templates.
        // More accurately, NgIf is declared in CommonModule from @angular/common.
        // BrowserModule imports CommonModule and re-exports it. 
        // The net effect is that an importer of BrowserModule gets CommonModule directives automatically.
        BrowserModule,
        BrowserAnimationsModule,
        CoreModule,
        MaterialModule,
        UsersModule,
        // IMPORTANT! Leaves the AppRoutingModule in the bottom to make the other module routing work.
        // But, there is always a but. If you are importing a module with routing config for lazy loading, the router will be matched before hits AppRoutingModule. 
        // This will make your empty router redirectng config ignored unless you put this module after AppRoutingModule. That's how the Angular router works.
        AppRoutingModule,
        // The module still imports AuthenticationModule so that its routes and components are mounted when the app starts. This we call eager loading.
        // The modules are NOT imported which will be fetched and mounted asynchronously when the user navigates to one of their routes. This we call lazy loading.
        // We need to use op-lock-screen component 
        AuthenticationModule
    ],
    // AppModule does not need the exports.
    // exports: [
    //   
    // ],
    // The view classes that belong to this module. Angular has three kinds of view classes: components, directives, and pipes.
    // Only modules can be added to module's imports. Components, directives and pipes are placed in module's declarations.
    // For example: Do not add NgModel or the FORMS_DIRECTIVES to the AppModule metadata's declarations. These directives belong to the FormsModule.
    // Components, directives, and pipes belong to one module only.
    // Never re-declare classes that belong to another module.
    declarations: [
        AppComponent
    ],
    // Creators of services that this module contributes to the global collection of services; they become accessible in all parts of the app.
    providers: [

    ],
    // The main application view, called the root component, that hosts all other app views. Only the root module should set this bootstrap property.
    bootstrap: [
        AppComponent
    ]
})
export class AppModule {
    // Diagnostic only: inspect router configuration
    // constructor(router: Router) {
    // console.log(`Routes: ${JSON.stringify(router.config, undefined, 2)}`);
    // }

    constructor(private injector: Injector) {
        ServiceLocator.injector = this.injector;
    }
}